package cn.udrm.water.base.v1.manager.service;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import cn.udrm.water.base.v1.commons.models.ZTreeNodeVo;
import cn.udrm.water.base.v1.manager.cache.BaseResourceCache;
import cn.udrm.water.base.v1.manager.dto.BaseResourceDto;
import cn.udrm.water.base.v1.manager.dto.BaseResourceDtoMapper;
import cn.udrm.water.base.v1.manager.dto.BaseRoleDto;
import cn.udrm.water.base.v1.manager.dto.BaseRoleDtoMapper;
import cn.udrm.water.base.v1.manager.entities.BaseResource;
import cn.udrm.water.base.v1.manager.entities.BaseRole;
import cn.udrm.water.base.v1.manager.repository.BaseResourceRepository;


@Service
@Transactional(readOnly=true)
@CacheConfig(cacheNames="base_resources")
public class BaseResourceService {

	@Autowired
	private BaseResourceRepository resourceRepository;
	@Autowired
	private BaseResourceCache resourceCache;
	@Autowired
	private BaseResourceDtoMapper resourceDtoMapper;
	@Autowired
	private BaseRoleDtoMapper roleDtoMapper;
	
	public BaseResourceDto getWithChildrensById(String id) {
		BaseResource withChildrensById = resourceRepository.getWithChildrensById(id);
		if (withChildrensById != null) {
			List<BaseResource> childrens = withChildrensById.getChildrens();
			BaseResourceDto dto = resourceDtoMapper.from(withChildrensById);
			if (childrens != null) {
				List<BaseResourceDto> from = resourceDtoMapper.from(childrens);
				dto.setChildrenDtos(from);
			}
			return dto;
		}
		return null;
	}
	
	/**
	 * 获取资源树（只获取第一层）
	 * @return
	 */
	public List<ZTreeNodeVo> getResourcesTree() {
		List<BaseResource> findByParentIsNull = resourceRepository.findByParentIsNull();
		if (findByParentIsNull != null) {
			List<ZTreeNodeVo> list = new ArrayList<ZTreeNodeVo>();
			findByParentIsNull.forEach((r) -> {
				list.add(new ZTreeNodeVo(r.getId(), r.getName(), "0", ""));
				List<BaseResource> childrens = r.getChildrens();
				if (childrens != null) {
					childrens.forEach((rChild) -> {
						list.add(new ZTreeNodeVo(rChild.getId(), rChild.getName(), r.getId(), ""));
					});
				}
			});
			return list;
		}
		return null;
	}
	
	public BaseResourceDto getWithRolesById(String id) {
		BaseResource withRolesById = resourceRepository.getWithRolesById(id);
		if (withRolesById != null) {
			List<BaseRole> roles = withRolesById.getRoles();
			BaseResourceDto from = resourceDtoMapper.from(withRolesById);
			if (roles != null) {
				List<BaseRoleDto> rolesDto = roleDtoMapper.from(roles);
				from.setRoleDtos(rolesDto);
			}
			return from;
		}
		return null;
	}
	
	@Transactional(readOnly=false)
	public BaseResourceDto save(BaseResourceDto resourceDto) {
		BaseResource baseResource = resourceDtoMapper.to(resourceDto);
		baseResource.setId(null);
		/*
		 * 设置父对象
		 */
		BaseResource parent = null;
		String parentGuid = resourceDto.getParentGuid();
		if (StringUtils.isNotBlank(parentGuid)) {
			parent = resourceCache.findSelfById(parentGuid);
		}
		if (parent != null && StringUtils.isNotBlank(parent.getId())) {
			baseResource.setParent(parent);
		}
		/*
		 * 设置所属角色
		 */
		List<BaseRole> roles = null;
		List<BaseRoleDto> roleDtos = resourceDto.getRoleDtos();
		if (roleDtos != null) {
			roles = new ArrayList<BaseRole>();
			for (BaseRoleDto baseRoleDto : roleDtos) {
				roles.add(new BaseRole(baseRoleDto.getId()));
			}
		}
		if (roles != null) {
			baseResource.setRoles(roles);
		}
		BaseResource saveAndFlush = resourceCache.saveAndFlush(baseResource);
		return resourceDtoMapper.from(saveAndFlush);
	}
	@Transactional(readOnly=false)
	public BaseResourceDto update(BaseResourceDto resourceDto) {
		BaseResource baseResource = resourceDtoMapper.to(resourceDto);
		/*
		 * 设置父对象
		 */
		BaseResource parent = null;
		String parentGuid = resourceDto.getParentGuid();
		if (StringUtils.isNotBlank(parentGuid)) {
			parent = resourceCache.findSelfById(parentGuid);
		}
		if (parent != null && StringUtils.isNotBlank(parent.getId())) {
			baseResource.setParent(parent);
		}
		/*
		 * 设置所属角色
		 */
		List<BaseRole> roles = null;
		List<BaseRoleDto> roleDtos = resourceDto.getRoleDtos();
		if (roleDtos != null) {
			roles = new ArrayList<BaseRole>();
			for (BaseRoleDto baseRoleDto : roleDtos) {
				roles.add(new BaseRole(baseRoleDto.getId()));
			}
		}
		if (roles != null) {
			baseResource.setRoles(roles);
		}
		BaseResource saveAndFlush = resourceCache.saveAndFlush(baseResource);
		return resourceDtoMapper.from(saveAndFlush);
	}
	
	/**
	 * 删除所有信息, 包括其级联的所有实体
	 * @param ids
	 */
	@Transactional(readOnly=false)
	public void deleteAll(String[] ids) {
		if (ids == null || ids.length == 0) {
			return;
		}
		List<BaseResource> departments = new ArrayList<BaseResource>();
		for (String id : ids) {
			departments.add(new BaseResource(id));
		}
		this.deleteAll(departments);
	}
	
	/**
	 * @param iterable
	 */
	@Transactional(readOnly=false)
	private void deleteAll(Iterable<BaseResource> iterable) {
		if (iterable == null || iterable.iterator() == null) {
			return;
		}
		Iterator<BaseResource> iterator = iterable.iterator();
		while (iterator.hasNext()) {
			BaseResource department = iterator.next();
			department = resourceCache.findSelfById(department.getId());
			resourceCache.delete(department);
		}
	}
	
	@Transactional(readOnly=false)
	public void deleteAllSelf(String[] ids) {
		if (ids == null || ids.length == 0) {
			return;
		}
		for (String id : ids) {
			resourceCache.deleteById(id);
		}
	}
}
